#include <carbon/core/thread.h>
#include <unistd.h>
#include <sched.h>

CARBON_NS_BEGIN

static void * Thread_threadProc(void *p) {
    Thread::Impl * impl = (Thread::Impl*)p;
    if ( impl && impl->fn ) impl->fn();
    return nullptr;
}

Thread::Thread() {}
    
Thread::Thread(Thread && other) : m_impl(std::move(m_impl)) {}
    
Thread::Thread(RunnableFn run) : Thread(std::move(run), std::string()) {}
    
Thread::Thread(RunnableFn run, const std::string &name) : m_impl(new Impl()) {
    int r;
    pthread_attr_t attr;
    r = pthread_attr_init(&attr); assert(r == 0);

    this->m_impl->active = true;
    this->m_impl->fn = std::move(run);
    r = pthread_create(&m_impl->th, &attr, Thread_threadProc, m_impl.get()); assert(r == 0);
    pthread_attr_destroy(&attr);    // 不再需要
    
    if ( !name.empty() ) pthread_setname_np(m_impl->th, name.c_str());
}

Thread::~Thread() {
    if ( !m_impl ) return;
    assert(!m_impl->active);
}

Thread & Thread::operator=(Thread &&other) {
    if ( this == &other ) return *this;

    assert( !m_impl || !this->m_impl->active);
    m_impl = std::move(other.m_impl);
    return *this;    
}

Thread::operator bool() const { return m_impl?m_impl->active:false; }

unsigned long Thread::id() const { return m_impl?(unsigned long)m_impl->th:0UL; }

bool Thread::joinable() const { return m_impl?m_impl->active:false; }

void Thread::join() {
    if ( !m_impl ) return;

    void * res = nullptr;
    int r = pthread_join(m_impl->th, &res); assert(r == 0);
    this->m_impl->active = false;   // 线程已经关闭
}


void Thread::yield() { sched_yield(); }    // #include <sched.h>



CARBON_NS_END
